package conf

import (
	"encoding/json"
	"fmt"
	"sync"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

// 此文件，定义程序配置，实现程序和数据库的连接
// 数据库连接是通过gorm.DB来实现的

// 定义程序配置
type Config struct {
	Mysql *Mysql
	// 启动程序时，需要监听ip:port
	Api *Api
}

// 让Config的返回值，不是指针类型
func (c *Config) String() string {
	js, _ := json.Marshal(c)
	return string(js)
}

// 定义Mysql
type Mysql struct {
	Host     string `json:"host" toml:"host" env:"host"`
	Port     int    `json:"port" toml:"port"`
	Database string `json:"database" toml:"database"`
	Username string `json:"username" toml:"username"`
	Password string `json:"password" toml:"password"`
	// 定义一个gorm.DB的缓存，避免同一个用户多次连接
	conn *gorm.DB
	// 定义一个锁，避免多个gorouting调用时，产生脏数据
	lock sync.Mutex
}

type Api struct {
	Apihost string
	Apiport int
}

// 定义一个函数，来实现默认配置
func DefaultConfig() *Config {
	return &Config{
		Mysql: &Mysql{
			Host:     "127.0.0.1",
			Port:     3306,
			Database: "vblog",
			Username: "vblog",
			Password: "123456",
		},
		Api: &Api{
			Apihost: "127.0.0.1",
			Apiport: 8899,
		},
	}
}

// dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
// db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

// 扩展Mysql的方法，实现gorm.DB中的dsn
func (m *Mysql) Dsn() string {
	return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		m.Username, m.Password, m.Host, m.Port, m.Database)
}

// 扩展Mysql的方法，实现gorm.DB
func (m *Mysql) Getconn() *gorm.DB {
	// 调用时加锁
	m.lock.Lock()
	// 调用完解锁
	defer m.lock.Unlock()
	// 判断是否有缓存的gorm.DB
	if m.conn == nil {
		db, err := gorm.Open(mysql.Open(m.Dsn()), &gorm.Config{})
		if err != nil {
			panic(err)
		}
		m.conn = db
	}
	return m.conn
}
